/*
* This software copyright by various authors including the RPTools.net
* development team, and licensed under the LGPL Version 3 or, at your option,
* any later version.
*
* Portions of this software were originally covered under the Apache Software
* License, Version 1.1 or Version 2.0.
*
* See the file LICENSE elsewhere in this distribution for license details.
*/
package net.rptools.maptool.client.ui.htmlframe;
import java.awt.Component;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import javax.swing.ComboBoxModel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.PlainDocument;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.FormView;
import javax.swing.text.html.HTML;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
public class HTMLPaneFormView extends FormView {
private static final Logger LOGGER = Logger.getLogger(HTMLPaneFormView.class);
private final HTMLPane htmlPane;
/**
* Creates a new HTMLPaneFormView.
*
* @param elem
* The element this is a view for.
* @param pane
* The HTMLPane this element resides on.
*/
public HTMLPaneFormView(Element elem, HTMLPane pane) {
super(elem);
htmlPane = pane;
}
@Override
protected Component createComponent() {
Component c = null;
AttributeSet attr = getElement().getAttributes();
HTML.Tag t = (HTML.Tag) attr.getAttribute(StyleConstants.NameAttribute);
if (t == HTML.Tag.TEXTAREA) {
JScrollPane sp = (JScrollPane) super.createComponent();
JTextArea area = (JTextArea) sp.getViewport().getView();
area.setLineWrap(true);
area.setWrapStyleWord(true);
c = new JScrollPane(area,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
} else {
c = super.createComponent();
}
return c;
}
@Override
protected void submitData(String data) {
// Find the form
Element formElement = null;
for (Element e = getElement(); e != null; e = e.getParentElement()) {
if (e.getAttributes().getAttribute(StyleConstants.NameAttribute) == HTML.Tag.FORM) {
formElement = e;
break;
}
}
if (formElement != null) {
AttributeSet att = formElement.getAttributes();
String action = "";
if (att.getAttribute(HTML.Attribute.ACTION) != null) {
action = att.getAttribute(HTML.Attribute.ACTION).toString();
}
String method = "get";
if (att.getAttribute(HTML.Attribute.METHOD) != null) {
method = att.getAttribute(HTML.Attribute.METHOD).toString().toLowerCase();
}
if (method.equals("json")) {
JSONObject jobj = new JSONObject();
String[] values = data.split("&"); // Is this safe? What if the data contains an "&"?
for (String v : values) {
String[] dataStr = v.split("=");
if (dataStr.length == 1) {
try {
jobj.put(URLDecoder.decode(dataStr[0], "utf8"), "");
} catch (UnsupportedEncodingException e) {
// Use the raw data.
jobj.put(dataStr[0], "");
}
} else if (dataStr.length > 2) {
jobj.put(dataStr[0], dataStr[1]);
} else {
try {
jobj.put(URLDecoder.decode(dataStr[0], "utf8"), URLDecoder.decode(dataStr[1], "utf8"));
} catch (UnsupportedEncodingException e) {
// Use the raw data.
jobj.put(dataStr[0], dataStr[1]);
}
}
}
try {
data = URLEncoder.encode(jobj.toString(), "utf8");
} catch (UnsupportedEncodingException e) {
// Use the raw data.
data = jobj.toString();
}
}
htmlPane.doSubmit(method, action, data);
}
}
@Override
protected void imageSubmit(String data) {
Element formElement = null;
for (Element e = getElement(); e != null; e = e.getParentElement()) {
if (e.getAttributes().getAttribute(StyleConstants.NameAttribute) == HTML.Tag.FORM) {
formElement = e;
break;
}
}
if (formElement != null) {
String imageMapName = data.replaceFirst("\\..*", "");
Map<String, String> fdata = new HashMap<String, String>();
fdata.putAll(getDataFrom(formElement, imageMapName));
StringBuilder sb = new StringBuilder();
for (String s : fdata.keySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(s).append("=").append(fdata.get(s));
}
sb.append("&").append(data);
submitData(sb.toString());
} else {
submitData(data);
}
}
private Map<String, String> getDataFrom(Element ele, String selectedImageMap) {
Map<String, String> vals = new HashMap<String, String>();
for (int i = 0; i < ele.getElementCount(); i++) {
Element e = ele.getElement(i);
AttributeSet as = e.getAttributes();
if (as.getAttribute(StyleConstants.ModelAttribute) != null || as.getAttribute(HTML.Attribute.TYPE) != null) {
String type = (String) as.getAttribute(HTML.Attribute.TYPE);
String name = (String) as.getAttribute(HTML.Attribute.NAME);
Object model = as.getAttribute(StyleConstants.ModelAttribute);
if (type == null && model instanceof PlainDocument) {// Text area has no HTML.Attribute.TYPE
PlainDocument pd = (PlainDocument) model;
try {
vals.put(name, encode(pd.getText(0, pd.getLength())));
} catch (BadLocationException e1) {
LOGGER.error(e1.getStackTrace());
}
} else if (type == null && model instanceof ComboBoxModel) {
vals.put(name, ((ComboBoxModel) model).getSelectedItem().toString());
} else if ("text".equals(type)) {
PlainDocument pd = (PlainDocument) model;
try {
vals.put(name, encode(pd.getText(0, pd.getLength())));
} catch (BadLocationException e1) {
LOGGER.error(e1.getStackTrace());
}
} else if ("submit".equals(type)) {
// Ignore
} else if ("image".equals(type)) {
if (name != null && name.equals(selectedImageMap)) {
String val = (String) as.getAttribute(HTML.Attribute.VALUE);
vals.put(name + ".value", encode(val == null ? "" : val));
}
} else if ("radio".equals(type)) {
if (as.getAttribute(HTML.Attribute.CHECKED) != null) {
vals.put(name, encode(encode((String) as.getAttribute(HTML.Attribute.VALUE))));
}
} else if ("checkbox".equals(type)) {
if (as.getAttribute(HTML.Attribute.CHECKED) != null) {
vals.put(name, encode(encode((String) as.getAttribute(HTML.Attribute.VALUE))));
}
} else if ("password".equals(type)) {
PlainDocument pd = (PlainDocument) model;
try {
vals.put(name, encode(pd.getText(0, pd.getLength())));
} catch (BadLocationException e1) {
LOGGER.error(e1.getStackTrace());
}
} else if ("hidden".equals(type)) {
vals.put(name, encode(encode((String) as.getAttribute(HTML.Attribute.VALUE))));
}
}
vals.putAll(getDataFrom(e, selectedImageMap));
}
return vals;
}
private String encode(String str) {
try {
return URLEncoder.encode(str, "utf-8");
} catch (UnsupportedEncodingException e) {
LOGGER.error(e.getStackTrace());
return str;
}
}
}